
/*
XPT2046 / AD7843 Touch Screen Driver for PIC32MX795F512L
Copyright (C) 2012 Craig Dawson, Aaron Mohtar, Craig Peacock

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include <p32xxxx.h>
#include "board.h"
#include "XPT2046.h"
//#include "lcdText.h"
#include "lcdDraw.h"

double ax = 127;
double bx = -11;

double ay = -7206;
double by = 7274;

void touchScrInit(unsigned char EnableInterrupt) {
    TS_CS_DIR = 0;
    TS_CS = 1;

    SPI4CONbits.SMP = 0; // Input data sampled at middle of data output time
    SPI4CONbits.CKP = 0; // Idle state of clock is low
    SPI4CONbits.CKE = 1; // Data output changes on transition from active to idle
    SPI4CONbits.MSTEN = 1; // Master mode
    SPI4BRG = 31; // 1.25 MHz
    SPI4CONbits.ON = 1; // Finally turn on SPI peripheral

    if (EnableInterrupt) {
        INTCONbits.INT4EP = 1; // Interrupt on falling edge??
        IPC4bits.INT4IP = 3; // Priority 3
        IPC4bits.INT4IP = 3; // Subpriority
        IFS0bits.INT4IF = 0; // Clear INT4 Flag;
        IEC0bits.INT4IE = 1; // Enable INT4 Interrupt;

        // Send command to XPT2046 to enable interrupts
        touchScrSPICommand(TS_SAMP_X);
    }
}

unsigned int touchScrSPICommand(unsigned int command) {
    unsigned char byte1;
    unsigned char byte2;

    TS_CS = 0;

    SPI4BUF = command; // Send Command
    while (!SPI4STATbits.SPIRBF);
    byte1 = SPI4BUF; // Read Dummy

    SPI4BUF = 0x00; // Send Dummy
    while (!SPI4STATbits.SPIRBF);
    byte1 = SPI4BUF; // Read Byte 1

    SPI4BUF = 0x00; // Send Dummy
    while (!SPI4STATbits.SPIRBF);
    byte2 = SPI4BUF; // Read Byte 2

    TS_CS = 1;

    printf("byte1 %d,byte2 %d", byte1, byte2);
    return ((byte1 << 5) + (byte2 >> 3));
}

unsigned char touchScrGetCord(unsigned int * scaledX, unsigned int * scaledY) {
    int x = 0;
    int y = 0;
    int i;

    // get average over 5 samples.
    for(i = 0; i<5;i++)
    {
        x += touchScrSPICommand(TS_SAMP_X);
        y += touchScrSPICommand(TS_SAMP_Y);
    }
    x/=5;
    y/=5;

    if (y) {

        // Scale Y to pixel value
        y = ay * y + by;

        if (y < 0) y = 0;
        else if (y >= 320) y = 319;

        // Scale X to pixel value
       // x = (ax * x + bx)*(1 + (float) (320 - y) / 320); // x = x * (1 + correction factor)
x = (ax * x + bx);
        if (x < 0) x = 0;
        else if (x >= 240) x = 239;

        *scaledY = y;
        *scaledX = x;
        // Pen pressed and cordinates calculated
        return (1);
    } else {
        return (0); // Screen not pressed
    }
}

void touchScrCalibrate() {
 
    unsigned int X1 = 100;
    unsigned int Y1 = 0;

    unsigned int X2 = 0;
    unsigned int Y2 = 0;
    unsigned int temp = 0;

    lcdFillScreen(WHITE);
    delayMs(500);
    lcdWriteString("Touch the circles", 50, 100, BLACK, WHITE);

    lcdDrawCircle(10, 10, 10, 0, BLACK);
    delayUs(1);

    do {
        X1 = touchScrSPICommand(TS_SAMP_X);
        delayMs(10);
    } while (X1 < 200);


    for (temp = 0; temp < 10; temp++) {
        Y1 += touchScrSPICommand(TS_SAMP_Y);
        delayUs(1);
        X1 += touchScrSPICommand(TS_SAMP_X);
        delayUs(1);
    }

    X1 = X1 / 10;
    Y1 = Y1 / 10;

    do {
        temp = touchScrSPICommand(TS_SAMP_X);
    } while (temp > 100);

    TS_CS = 1;

    lcdDrawRectangle(0, 0, 20, 20, WHITE, 1);

    delayMs(1000);

    lcdDrawCircle(229, 309, 10, 0, BLACK);

    TS_CS = 0;
    do {
        X2 = touchScrSPICommand(TS_SAMP_X);
        delayMs(10);
    } while (X2 < 100);

 
    for (temp = 0; temp < 10; temp++) {
        Y2 += touchScrSPICommand(TS_SAMP_Y);
        delayUs(1);
        X2 += touchScrSPICommand(TS_SAMP_X);
        delayUs(1);
    }

    X2 = X2 / 10;
    Y2 = Y2 / 10;

    ax = (double) (229 - 10) / (X2 - X1);
    bx = 230 - ax*X2;

    ay = (double) (309 - 10) / ((double) Y2 - Y1);
    by = 310 - ay*Y2;

    TS_CS = 1;

    lcdDrawRectangle(50, 100, 58, 239, WHITE, 1);
    lcdWriteString("Calibration completed", 50, 100, BLACK, WHITE);

    lcdDrawRectangle(219, 299, 239, 319, WHITE, 1);
    delayMs(1000);
    lcdDrawRectangle(50, 100, 239, 108, WHITE, 1);


    lcdDisplayVariable("X1:", X1, 4, "", 20, 100, BLACK, WHITE);
    lcdDisplayVariable("Y1:", Y1, 4, "", 20, 110, BLACK, WHITE);
    lcdDisplayVariable("X2:", X2, 4, "", 20, 120, BLACK, WHITE);
    lcdDisplayVariable("Y2:", Y2, 4, "", 20, 130, BLACK, WHITE);

    lcdDisplayVariable("ax:", (unsigned int) (ax * 1000), 4, "", 20, 140, BLACK, WHITE);
    lcdDisplayVariable("bx: -", (unsigned int) (-1 * bx), 4, "", 20, 150, BLACK, WHITE);
    lcdDisplayVariable("ay: -", (unsigned int) (ay*-1000), 4, "", 20, 160, BLACK, WHITE);
    lcdDisplayVariable("by:", (unsigned int) by, 4, "", 20, 170, BLACK, WHITE);

    delayMs(1000);

    lcdWriteString("Touch screen to continue", 20, 200, BLACK, WHITE);

    TS_CS = 0;
    do {
        temp = touchScrSPICommand(TS_SAMP_X);
        delayMs(10);
    } while (temp < 200);

    TS_CS = 1;
}

void __attribute((interrupt(ipl3), vector(_EXTERNAL_4_VECTOR), nomips16)) _TouchScreenHandler(void) {
    IFS0bits.INT4IF = 0; // Clear INT4 Flag;
    // printf("PenIrq\r\n");

}

